package cn.zwx.security.example.security.jwt;

import cn.hutool.core.util.StrUtil;
import cn.zwx.security.example.config.JWTConfig;
import cn.zwx.security.example.entity.extend.SelfUserEntity;
import cn.zwx.security.example.utils.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @description: JWT认证过滤器
 * @projectName:spring-boot-security-example
 * @see:cn.zwx.security.example.security.jwt
 * @author:zhangwenxue
 * @createTime:2021/6/23 16:30
 * @version:1.0
 */
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {

    private Logger logger = LoggerFactory.getLogger(JWTAuthenticationTokenFilter.class);


    public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取请求头中JWT的Token
        JWTConfig jwtConfig = SpringUtil.getBean(JWTConfig.class);
        String tokenHeader = request.getHeader(jwtConfig.getTokenHeader());
        if (null!=tokenHeader && tokenHeader.startsWith(jwtConfig.getTokenPrefix())) {
            try {
                // 截取JWT前缀
                String token = tokenHeader.replaceFirst(jwtConfig.getTokenPrefix(),"");
                // 解析JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(jwtConfig.getSecret())
                        .parseClaimsJws(token)
                        .getBody();
                // 获取用户名
                String username = claims.getSubject();
                String userId=claims.getId();
                if(StrUtil.isNotBlank(username)&&StrUtil.isNotBlank(userId)) {
                    // 获取角色
                    List<GrantedAuthority> authorities = new ArrayList<>();
                    String authority = claims.get("authorities").toString();
                    if(StrUtil.isNotBlank(authority)){
                        List<Map<String,String>> authorityMap = JSONObject.parseObject(authority, List.class);
                        for(Map<String,String> role : authorityMap){
                            if(Objects.nonNull(role)) {
                                authorities.add(new SimpleGrantedAuthority(role.get("authority")));
                            }
                        }
                    }
                    //组装参数
                    SelfUserEntity selfUserEntity = new SelfUserEntity();
                    selfUserEntity.setUsername(claims.getSubject());
                    selfUserEntity.setUserId(Long.parseLong(claims.getId()));
                    selfUserEntity.setAuthorities(authorities);
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(selfUserEntity, userId, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (ExpiredJwtException e){
                logger.error("Token过期",e);
            } catch (Exception e) {
                logger.error("Token无效",e);
            }
        }
        filterChain.doFilter(request, response);
        return;
    }
}
